package com.xingkong.behavior.model;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * @author xingkong
 *
 */
public class BehaviorModel {
	private Graph graph;
	private JSONArray cascadeInfoJSON;
	private Integer countActiveNode=0;
	private Integer maxiterative=Integer.MAX_VALUE;
	public void setMaxiterative(Integer maxiterative) {
		this.maxiterative = maxiterative;
	}

	private static String realTimeMessage="";
	public BehaviorModel(Graph graph) {
		this.graph = graph;
	}

	public void LTM() {
		countActiveNode=0;//归零，存储算法本次运行的激活节点个数
		List<Vertex> previousActiveVertexList=new ArrayList<Vertex>();//存储从0到t-1时刻所有激活的节点
		cascadeInfoJSON=new JSONArray();//存储节点的迭代激活信息
		Map<String,Boolean> previousActiveVertextSearch=new HashMap<String,Boolean>();
		if(this.maxiterative>0){
			realTimeMessage=realTimeMessage+"\n"+"初始激活节点：\n";//设置实时运行过程信息
		}
		else{
			realTimeMessage="初始激活节点：\n";
		}
		JSONArray initCascadeInfo=new JSONArray();
		for(Vertex vertex:graph.getVertexList()){//初始化
			if(vertex.isActive()){
				previousActiveVertextSearch.put(vertex.getID(),true);//设置已经激活的节点作为初始节点
				JSONObject initcascadeActive=new JSONObject();//初始已被激活节点信息
				initcascadeActive.put("active", vertex.getID()+","+findRealInfo(vertex.getID()));//设置已被激活的节点
				initcascadeActive.put("start", new JSONArray());//start表示由哪些节点激活了active中的节点，初始时start为空
				initCascadeInfo.add(initcascadeActive);
				realTimeMessage+=vertex.getID()+" ";
			}
		}
		cascadeInfoJSON.add(initCascadeInfo);
		realTimeMessage+="\n";
		Map<String,Boolean> tempActiveVertex=new HashMap<String,Boolean>();
		int count=0;
		
		while (!graph.getVertexList().equals(previousActiveVertexList)) {
			System.out.println("第"+(++count)+"次迭代");
			if(count>maxiterative) {
				System.out.println("终止第"+(count)+"次迭代");
				break;
			}
			realTimeMessage+="第"+(count)+"次迭代"+"\n";
			JSONArray tempCascadeInfo=new JSONArray();
			previousActiveVertexList.clear();
			tempActiveVertex.clear();
			//previousActiveVertexList.addAll(graph.getVertexList());// 深复制
			try {
				previousActiveVertexList=deepCopy(graph.getVertexList());//深复制
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			// 扫描非激活顶点
			for (Vertex vertex:graph.getVertexList()) {
				if(!vertex.isActive()){
					JSONArray thiscascade=new JSONArray();
					JSONObject thicascadeActive=new JSONObject();
					double sum = 0;
					for (Map.Entry<String,Double> entry:vertex.getInVertexMap().entrySet()) {
						if(previousActiveVertextSearch.get(entry.getKey())!=null){
							System.out.println(entry.getKey()+"贡献给"+vertex.getID()+":"+entry.getValue());
							realTimeMessage+=entry.getKey()+"贡献给"+vertex.getID()+":"+entry.getValue()+"\n";
							sum += entry.getValue();
							thiscascade.add(entry.getKey()+","+findRealInfo(entry.getKey()));
						}
					}
					Double threshold=vertex.getThreshold();
//					Double temp_1=1.0;
//					if(threshold.equals(temp_1))  threshold+=-getRandom();
//					else threshold+=getRandom()+1;
					System.out.println(vertex.getID()+"尝试被激活,"
							+sum+":"+threshold+","+(sum>threshold?"成功":"失败"));
					realTimeMessage+=vertex.getID()+"尝试被激活,"
							+sum+":"+threshold+","+(sum>threshold?"成功":"失败")+"\n";
					if (sum > threshold) {
						vertex.setActive(true);
						countActiveNode++;
						//tempCascadeInfo.add(vertex.getID());
						thicascadeActive.put("active", vertex.getID()+","+findRealInfo(vertex.getID()));
						thicascadeActive.put("start", thiscascade);
						tempCascadeInfo.add(thicascadeActive);
						tempActiveVertex.put(vertex.getID(), true);
//						previousActiveVertextSearch.put(vertex.getID(), true);
					}
				}
				
			}
			previousActiveVertextSearch.putAll(tempActiveVertex);
			if(tempCascadeInfo.size()>0)
				cascadeInfoJSON.add(tempCascadeInfo);
		}
	}

	public void ICM() {
		countActiveNode=0;//归零，存储算法本次运行的激活节点个数
		List<Vertex> previousActiveVertexList=new ArrayList<Vertex>();//记录上一次被激活的节点
		cascadeInfoJSON=new JSONArray();
		if(this.maxiterative>0){
			realTimeMessage=realTimeMessage+"\n"+"初始激活节点：\n";
		}
		else{
			realTimeMessage="初始激活节点：\n";
		}
		JSONArray initCascadeInfo=new JSONArray();
		for(Vertex vertex:graph.getVertexList()){//初始化信息
			if(vertex.isActive()){
				previousActiveVertexList.add(vertex);//设置已经激活的节点作为初始节点
				JSONObject initcascadeActive=new JSONObject();;//初始已被激活节点信息
				initcascadeActive.put("active", vertex.getID()+","+findRealInfo(vertex.getID()));//设置已被激活的节点
				initcascadeActive.put("start", new JSONArray());//start表示由哪些节点激活了active中的节点，初始时start为空
				initCascadeInfo.add(initcascadeActive);
				realTimeMessage+=vertex.getID()+" ";
			}
		}
		cascadeInfoJSON.add(initCascadeInfo);
		realTimeMessage+="\n";
		List<Vertex> tempActiveVertexList=new ArrayList<Vertex>();
		int count=0;
		while (!previousActiveVertexList.isEmpty()) {// 上一次被激活的顶点是否为空
			tempActiveVertexList.clear();
			System.out.println("第"+(++count)+"次迭代");
			if(count>maxiterative) {
				System.out.println("终止第"+(count)+"次迭代");
				break;
			}
			realTimeMessage+="第"+(count)+"次迭代"+"\n";
			JSONArray tempCascadeInfo=new JSONArray();
			for (Vertex previousActiveVertex:previousActiveVertexList) {
				for(Vertex vertex:graph.getVertexList()){
					if(vertex.isActive()==false){//只有该节点没激活时才能继续向下走
						JSONArray thiscascade=new JSONArray();
						JSONObject thicascadeActive=new JSONObject();
						for(Map.Entry<String,Double> entry:vertex.getInVertexMap().entrySet()){
							if(entry.getKey().equals(previousActiveVertex.getID())){//vertex顶点入边的起点是previousActiveVertex点
								double random=getRandom();
								System.out.println(previousActiveVertex.getID()+"尝试激活"
										+vertex.getID()+","+random+":"+entry.getValue()+","+(random<entry.getValue()?"成功":"失败"));
								thiscascade.add(previousActiveVertex.getID()+","+findRealInfo(previousActiveVertex.getID()));
								realTimeMessage+=previousActiveVertex.getID()+"尝试激活"
										+vertex.getID()+","+random+":"+entry.getValue()+","+(random<entry.getValue()?"成功":"失败")+"\n";
								Double entry_value=entry.getValue();
//								Double temp_1=1.0;
//								if(entry_value.equals(temp_1))  entry_value+=-getRandom();
//								else entry_value+=getRandom()+1;
								if(random<entry_value){
									vertex.setActive(true);
									countActiveNode++;
									tempActiveVertexList.add(vertex);
//									tempCascadeInfo.add(vertex.getID());
									thicascadeActive.put("active", vertex.getID()+","+findRealInfo(vertex.getID()));
									thicascadeActive.put("start", thiscascade);
									tempCascadeInfo.add(thicascadeActive);
								}
							}
						}
					}
				}
			}
			previousActiveVertexList.clear();
			previousActiveVertexList.addAll(tempActiveVertexList);
			if(tempCascadeInfo.size()>0)
				cascadeInfoJSON.add(tempCascadeInfo);
		}
	}
	
	/**
	 * @param src 源List对象
	 * @return 被深度复制的另一份对象
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {//深度复制
		ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
		ObjectOutputStream out = new ObjectOutputStream(byteOut);
		out.writeObject(src);

		ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
		ObjectInputStream in = new ObjectInputStream(byteIn);
		@SuppressWarnings("unchecked")
		List<T> dest = (List<T>) in.readObject();
		return dest;
	}
	private String findRealInfo(String ID){
		for(Vertex vertex:graph.getVertexList()){
			if(vertex.getID().equals(ID)){
				return vertex.getLabel();
			}
		}
		return null;
	}
	public double getRandom(){
		return Math.random();
	}
	public JSONArray getCascadeInfoJSON() {
		return cascadeInfoJSON;
	}

	public Graph getGraph() {
		return graph;
	}

	public static void main(String[] args) {
		//测试LTM算法
//		Graph g=new Graph();
//		g.testLTM();
//		System.out.println("原始节点信息");
//		System.out.println(g.getVertexList());
//		BehaviorModel bm=new BehaviorModel(g);
//		bm.LTM();
//		System.out.println("运行后节点信息");
//		System.out.println(bm.getGraph().getVertexList());
		
		//测试ICM算法
//		Graph g=new Graph();
//		g.testICM();//初始化测试数据
//		System.out.println("原始节点信息");
//		System.out.println(g.getVertexList());
//		BehaviorModel bm=new BehaviorModel(g);
//		bm.ICM();
//		System.out.println("运行后节点信息");
//		System.out.println(bm.getGraph().getVertexList());
//		Converter converter=new Converter();
//		converter.graphConvertToJson(g);
//		converter.printToFile("e:\\myjson.json");
//		converter.readJsonFromFile("e:\\myjson.json");
		Graph g=new Graph();
		Converter converter=new Converter();
		//g.testLTM();
//		converter.reSerializable("e:\\original.json", "e:\\original.serial");
		g=converter.readJsonFromFile("e:\\original.json",false,null,null);
		System.out.println("原始节点信息");
		System.out.println(g.getVertexList());
		BehaviorModel bm=new BehaviorModel(g);
		bm.LTM();
		System.out.println("运行后节点信息");
		System.out.println(bm.getGraph().getVertexList());
		System.out.println("迭代激活信息");
		System.out.println(bm.getCascadeInfoJSON());
//		converter.graphConvertToJson(g);
//		converter.printToFile("e:\\data.json");
	}
	public Integer getCountActiveNode() {
		return countActiveNode;
	}
	public static String getRealTimeMessage() {
		return realTimeMessage;
	}

	public static void setRealTimeMessage(String realTimeMessage) {
		BehaviorModel.realTimeMessage = realTimeMessage;
	}
}
